/*
 * Copyright 2011-2012 Redia A/S
 * 
 * This file is part of Redias Library App for Android.
 *
 *  Redia Library App for Android is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Redia Library App for Android is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with Redia Library App for Android.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.redia.libraryapp.authentication;

import java.util.List;
import java.util.Map;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import dk.redia.lib.log.Log;
import dk.redia.lib.utils.AppApplication;
import dk.redia.lib.utils.AppConfiguration;
import dk.redia.lib.xmlrpc.XmlRpcClientResultListener;
import dk.redia.lib.xmlrpc.XmlRpcResultDumper;
import dk.redia.lib.xmlrpc.XmlRpcResultUtils;
import dk.redia.libraryapp.R;
import dk.redia.libraryapp.model.LibraryModel;
import dk.redia.libraryapp.model.ReservationBranch;
import dk.redia.libraryapp.model.ReservationBranchModel;
import dk.redia.libraryapp.model.ReservationBranchModelListener;
import dk.redia.libraryapp.xmlrpc.library.XmlRpcClient;

public class Authentication {
	
	private boolean authenticated;
	private String preferredBranch;
	private String preferredBranchName;
	private String userName;
	private static Authentication instance;
	
	private final static String PREF_KEY_SAVE_PREFERENCES = "savePreferences";
	private final static String PREF_KEY_BORROWER_CARD_ID = "borrowerCardId";
	private final static String PREF_KEY_BORROWER_PASSWORD = "borrowerPassword";
	protected static final String logTag = "Authentication";
	
	public static Authentication getInstance() {
		if (instance==null) {
			instance = new Authentication();
		}
		return instance;
	}

	private SharedPreferences getPrefs() {
		return AppApplication.getAppContext().getSharedPreferences("authentication", Context.MODE_PRIVATE);
		
	}
	
	private Editor getPrefsEditor() {
		return getPrefs().edit();
	}
	
	public void authenticate(final AuthenticationListener l) {
		XmlRpcClient.getInstance().authenticate(
				AppConfiguration.getInstance().getCustomerId(), 
				AppConfiguration.getInstance().getApiKey(),
				getBorrowerCardId(), 
				getBorrowerPassword(), new XmlRpcClientResultListener() {
					
					public void callFailed(String message) {
						Log.w(Authentication.logTag, "Error during call to XML-RPC method authenticate: " + message);
						l.failed(AppApplication.getAppContext().getResources().getString(R.string.internalErrorText));
					}
					
					public void callCompleted(Object resultObj) {
						XmlRpcResultDumper.dump(resultObj);
						Log.d(Authentication.logTag, "Received response from call to authenticate");
						XmlRpcResultDumper.dump(resultObj);
						Map<String, Object> r = XmlRpcResultUtils.unpackStandardResult(resultObj);
//						Boolean result = false;
						Boolean auth = false;
//						String message = "";

						try {
//							result = (Boolean)r.get("result");
							auth = (Boolean)r.get("authenticated");
//							message = (String)r.get("message");
							
							if (auth!=null && auth) {
								Map<String, Object> data = XmlRpcResultUtils.unpackStruct(r.get("data"));
								Map<String, Object> patronData = XmlRpcResultUtils.unpackStruct(data.get("patron"));
								// Remove the line below to test what happens if user has
								// no preferred reservation pickup branch configured
								Authentication.getInstance().preferredBranch = (String)patronData.get("preferredBranch");
								Authentication.getInstance().userName = (String)patronData.get("name");

								authenticated = true;
								
								ReservationBranchModel.getInstance().getReservationBranches(new ReservationBranchModelListener() {
									
									public void getReservationsFailure(String message) {
										Log.w(logTag, "Failed to retrieve branch names");
										preferredBranchName = "";
										l.succeeded();
									}
									
									public void getReservationBranchesResult(List<ReservationBranch> rbs) {
										preferredBranchName = "";
										for (ReservationBranch reservationBranch : rbs) {
											if (reservationBranch.getId().equals(preferredBranch)) {
												preferredBranchName = reservationBranch.getName();
											}
										}
										l.succeeded();
									}
								});
								
								
							} else {
								authenticated = false;
								l.failed(AppApplication.getAppContext().getResources().getString(R.string.failedToLogOnText));
							}
							
						} catch (ClassCastException e) {
							Log.e(Authentication.logTag, "Failed to decode result from call to authenticate: " + e.getMessage());
							e.printStackTrace();
						}
					}
				});
	}
	
	public String getUserName() {
		return userName;
	}
	
	public String getPreferredBranch() {
		return preferredBranch;
	}
	
	public String getPreferredBranchName() {
		return preferredBranchName;
	}
	
	public boolean savingCredentials() {
		SharedPreferences prefs = getPrefs();
		return prefs.getBoolean(Authentication.PREF_KEY_SAVE_PREFERENCES, true);
	}
	
	public void setSaveCredentials(boolean value) {
		Editor editor = getPrefsEditor();
		editor.putBoolean(Authentication.PREF_KEY_SAVE_PREFERENCES, value);
		editor.commit();
	}
	
	public void setBorrowerCardId(String id) {
		Editor editor = getPrefsEditor();
		editor.putString(Authentication.PREF_KEY_BORROWER_CARD_ID, id);
		editor.commit();
	}
	
	public String getBorrowerCardId() {
		return getPrefs().getString(Authentication.PREF_KEY_BORROWER_CARD_ID, "");
	}
	
	public void setBorrowerPassword(String password) {
		Editor editor = getPrefsEditor();
		editor.putString(Authentication.PREF_KEY_BORROWER_PASSWORD, password);
		editor.commit();
	}
	
	public String getBorrowerPassword() {
		return getPrefs().getString(Authentication.PREF_KEY_BORROWER_PASSWORD, "");
	}
	
	
	public Authentication() {
		authenticated = false;
	}
	
	public boolean isAuthenticated() {
		return authenticated;
	}
	
	public void setAuthenticated(boolean authenticated) {
		this.authenticated = authenticated;
	}
}
